iT邦幫忙

2024 iThome 鐵人賽

DAY 2
0
Software Development

輕鬆學習設計模式Design Pattern系列 第 2

Day 2 策略模式 Strategy Pattern

  • 分享至 

  • xImage
  •  

在日常開發中,我們常需要對檔案進行壓縮,而不同的壓縮格式(如 Zip、Rar、7z 等)各有其優缺點。有時候我們希望能夠根據當下需求自由地切換壓縮方式,而不需要改動太多的程式碼。這時候策略模式 Strategy Pattern 就可以幫我們輕鬆實現這個需求。

什麼是策略模式?

策略模式是一種行為設計模式,它可以讓我們定義一系列的演算法,將每個演算法封裝起來,並讓它們可以互相替換使用。這樣一來程式碼不僅更加靈活,也更容易擴展跟維護了。

簡單來說,策略模式就是讓程式可以隨意更換的「策略」,讓程式能夠靈活地應對不同種的情況。

策略模式在壓縮器中的應用

假設你正在開發一個檔案壓縮的功能。一開始你可能只支援 ZIP 格式壓縮。但隨著使用者需求的增加,你發現需要添加 RAR、7Z 等其他壓縮格式的支援。

你的程式碼可能會寫成這樣:

class Compressor {
public:
    void compress(const std::string& filename, const std::string& format) {
        if (format == "zip") {
            // ZIP 壓縮邏輯
        } else if (format == "rar") {
            // RAR 壓縮邏輯
        } else if (format == "7z") {
            // 7Z 壓縮邏輯
        } else {
            throw std::runtime_error("不支援的格式");
        }
    }
};

這種方法的問題在於每次新增新的壓縮格式時,都需要修改 Compressor 類別。這違反了「開放封閉原則」,也就是軟體應該對擴展開放,對修改封閉。

讓我們看看如何使用策略模式來改進這個設計:

我們先定義一個壓縮策略介面 CompressionStrategy,

class CompressionStrategy {
public:
    virtual void compress(const std::string& filename) = 0;
    virtual ~CompressionStrategy() = default;
};

然後為每種壓縮格式實作具體的策略,分別為 ZipStrategy、RarStrategy、SevenZipStrategy,

class ZipStrategy : public CompressionStrategy {
public:
    void compress(const std::string& filename) override {
        std::cout << "使用 ZIP 壓縮 " << filename << " 檔案\n";
    }
};

class RarStrategy : public CompressionStrategy {
public:
    void compress(const std::string& filename) override {
        std::cout << "使用 RAR 壓縮 " << filename << " 檔案\n";
    }
};

class SevenZipStrategy : public CompressionStrategy {
public:
    void compress(const std::string& filename) override {
        std::cout << "使用 7Z 壓縮 " << filename << " 檔案\n";
    }
};

根據此情境在設計時,建立一個 Compressor 壓縮器,又為稱上下文類別,這個 Compressor 類別可以根據需求動態選擇不同的壓縮策略。

class Compressor {
private:
    std::unique_ptr<CompressionStrategy> strategy;

public:
    Compressor(std::unique_ptr<CompressionStrategy> strategy) 
        : strategy(std::move(strategy)) {}

    void setStrategy(std::unique_ptr<CompressionStrategy> newStrategy) {
        strategy = std::move(newStrategy);
    }

    void compress(const std::string& filename) {
        strategy->compress(filename);
    }
};

當需要使用壓縮器時,可以這樣寫,Compressor 將會執行已經選擇的壓縮策略進行壓縮,然後也可以執行期間更換壓縮策略,

int main() {
    Compressor compressor(std::make_unique<ZipStrategy>());
    compressor.compress("file1.txt");  // 輸出:使用 ZIP 壓縮 file1.txt 檔案

    compressor.setStrategy(std::make_unique<SevenZipStrategy>());
    compressor.compress("file2.txt");  // 輸出:使用 7Z 壓縮 file2.txt 檔案

    return 0;
}

策略模式的優點

使用策略模式,讓我們能夠方便地擴展壓縮器的功能,當需要增加新的壓縮格式時,只需新增一個實作了 CompressionStrategy 介面,並將其設定到 Compressor 中即可,完全不需要修改現有 Compressor 與其它壓縮策略的程式碼。另外策略模式還能讓程式碼變得更加清晰易懂,避免大量的條件判斷或分支邏輯,使系統在面對複雜業務需求時,依然能保持穩定和易於維護。

總結

策略模式是一個很實用的設計模式,能夠有效解決系統中某些功能需要頻繁變動或擴展的問題。在這個壓縮器範例中,我們看到如何使用策略模式來靈活地切換壓縮格式,並保持程式碼的清晰和可維護性。並能在日後的開發中靈活運用它,讓你的程式碼更加優雅。

更多C++語言相關的文章,歡迎追蹤我的部落格
https://shengyu7697.github.io/cpp-strategy-pattern/


上一篇
Day 1 設計模式入門:什麼是設計模式?為什麼要學習它們?
下一篇
Day 3 觀察者模式 Observer Pattern
系列文
輕鬆學習設計模式Design Pattern30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言